import Qs from 'qs'
import axios from 'axios'
import {
  Message,
  MessageBox
} from 'element-ui'
import store from '@/store'
import {
  resPost
} from './requestEncy'
import {
  getToken
} from '@/utils/auth'
import JSEncrypt from 'jsencrypt'
import CryptoJS from '@/utils/aesJiaJM'
import CancelRequest from '@/utils/cancelRequest.js'
JSEncrypt.$getRsaCode = (str) => {
  const pubKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvCkyEkJSy7QWRPZzceERKiMEtdPfCvJbEJj93IqE4nX4CAwuNESEx5jVTBG7TfvOCbUTdcRh9MHPQ0XldVPs/HO8v95OMUXh1+bDrDBPPh3tSgh+2YZB/WxJAY6V6kNPXXnsZBHCpQqTt0INbPrjTGcVNKFphDSmuom3/TxHd5c0dH33xGSL8U0/KXTWto3QmhdAOqCErhMdn6MMNjyaU5qnHq9x0B5shEHSyp3hkBRCcnScnCRRVqTNbeJ2iiyfX6Dd8RqVA9emlj9jHetU+ot7DwwhdMDS2vT6xb32HHEYemN85bPXpjkawuHznKks0dmc5ceHxAalNpmneIVvMwIDAQAB`// ES6 模板字符串 引用 rsa 公钥
  const encryptStr = new JSEncrypt()
  encryptStr.setPublicKey(pubKey)
  const data = encryptStr.encrypt(str)
  return data
}
const getQueryObject = function(url) {
  url = url == null ? window.location.href : url
  const search = url.substring(url.lastIndexOf('?') + 1)
  const obj = {}
  const reg = /([^?&=]+)=([^?&=]*)/g
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1)
    let val = decodeURIComponent($2)
    val = String(val)
    obj[name] = val
    return rs
  })
  return obj
}
let tipReLogin = false // 402提示标识，防止接口并发重复弹框
// 创建axios实例
const service = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 5 * 60 * 1000, // 请求超时时间
  transformRequest: [(data) => {
    data = Qs.stringify(data)
    return data
  }],
  transformResponse: [(data) => {
    return data
  }],
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})

const cancelwhiteList = [
  '/backend/sysDictionary/getDictByCode',
  'backend/sysDictionary/getDictByCode',
  '/backend/hyTemplateManage/query',
  '/backend/hyExpertManage/expertGoodAtField',
  '/backend/sys/sysConfig/getByName',
  '/backend/craftsmanLibrary/switchStatusChange',
  '/backend/dailyFocus/queryData',
  '/backend/sysPageInfo/query',
  '/backend/pageRegister/queryRegByComId',
  '/API-ENTERPRISE-APP/app/sysConfig/getByName',
  '/backend/sysClassify/getClassifyTree',
  '/backend/learnClassify/getClassifyTree'
]
const CancelToken = axios.CancelToken
const removePending = (config) => {
  for (const k in store.state.app['axiosPromiseCancel']) {
    if (store.state.app['axiosPromiseCancel'][k].u === config.url + '&' + config.method) {
      store.state.app['axiosPromiseCancel'][k].f() // 执行取消操作
      store.state.app['axiosPromiseCancel'].splice(k, 1) // 把这条记录从数组中移除
    }
  }
}
// request拦截器

service.interceptors.request.use(config => {
  // 暂时注释
  if (store.getters.token) {
    config.headers['ttsxyhcs'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
  }
  if (process.env.NODE_ENV === 'development') {
    config.headers['ttsxbid'] = 1
    config.headers['ttsxhost'] = '127.0.0.1'
  }
  if (config.encyType && config.encyType === 'aes') {
    console.log('aes')
  } else {
    if (config.method === 'get') {
      const params = config.params
      for (const key in params) {
        if (params[key] === undefined || params[key] === null) {
          params[key] = ''
        }
      }
      config.params = params
      const signParams = { ...config.params || {}, ...getQueryObject(config.url) }
      config = resPost(config, signParams)
    } else if (config.method === 'post') {
      const params = config.data
      for (const key in params) {
        if (params[key] === undefined || params[key] === null) {
          params[key] = ''
        }
      }
      config.data = params
      const signParams = { ...config.data || {}, ...getQueryObject(config.url) }
      config = resPost(config, signParams)
    }
  }
  /* if (cancelwhiteList.indexOf(config.url) === -1) { // 不在白名单中
    removePending(config) // 在一个ajax发送前执行一下取消操作
  }

  config.cancelToken = new CancelToken((c) => {
    store.state.app['axiosPromiseCancel'].push({
      u: config.url + '&' + config.method,
      f: c
    })
  })*/

  // 在请求开始之前检查先前的请求，如果是重复请求，删除之前的
  CancelRequest.removePendingRequest(config, '请求前')
  // 如果不存在就将当前请求添加到pendingRequest
  CancelRequest.addPendingRequest(config)
  if (store.getters.checkurl.length > 0) {
    const arr = store.getters.checkurl
    const user = store.getters.user
    // 兼容部分接口不是以/开头，导致无法正确匹配
    const url = config.url.substring(0, 1) === '/' ? config.url : '/' + config.url
    const obj = arr.find(a => url.includes(a.rcUrl))
    if (obj) {
      const phoneAes = CryptoJS.$aesJieM(user.phoneNumber)
      const pat = /(\d{3})\d*(\d{4})/
      const phone = phoneAes.replace(pat, '$1****$2')
      return new Promise((resolve, reject) => {
        if (obj.rcType === 'sms') { // 需要发送短信二次验证
          MessageBox.confirm(`此操作需要向您手机号码为：${phone}发送短信验证码确认, 是否继续?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
            closeOnClickModal: false
          }).then(() => {
            // 发送验证码
            service({
              baseURL: '/API-ENTERPRISE-BACKEND/',
              url: '/backend/sendSmsCodeLogin',
              method: 'post',
              data: {
                smsType: '4'
              }
            }).then((res) => {
              // 输入验证码
              MessageBox.prompt(res.data.msg || '请输入验证码，验证码已发送到' + phone, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                showInput: true,
                inputPattern: /\S/,
                inputType: 'text',
                inputPlaceholder: '请输入验证码',
                inputErrorMessage: '验证码不能为空',
                closeOnClickModal: false
              }).then(({ value }) => {
                config.headers['rcType'] = obj.rcType
                const key = 'e2f29cb8df39a368e2f29cb8df39a368,5e92442523d44e7c167fcc6f98d40157'
                config.headers['rcValue'] = JSEncrypt.$getRsaCode(JSON.stringify({ value, key }))
                resolve(config)
              }).catch(() => {
                // 如果不输入验证码直接取消，需要将已发送的验证码删除，防止下次调用发送验证码接口失败
                reject({ msg: '已取消验证码校验' })
              })
            }).catch(() => {
              reject({ msg: '发送验证码失败，请联系管理员' })
            })
          }).catch(() => {
            reject({ msg: '已取消验证码校验' })
          })
        } else {
          MessageBox.prompt('请输入管理员密码', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            showInput: true,
            inputPattern: /\S/,
            inputType: 'password',
            inputErrorMessage: '请输入管理员密码'
          }).then(({ value }) => {
            config.headers['rcType'] = obj.rcType
            const key = 'e2f29cb8df39a368e2f29cb8df39a368,5e92442523d44e7c167fcc6f98d40157'
            config.headers['rcValue'] = JSEncrypt.$getRsaCode(JSON.stringify({ value, key }))
            resolve(config)
          }).catch(() => {
            reject({ msg: '已取消管理员密码校验' })
          })
        }
      })
    } else {
      return config
    }
  } else {
    return config
  }
}, error => {
  // Do something with request error
  Promise.reject(error)
})

// respone拦截器
service.interceptors.response.use(
  response => {
    // removePending(response.config) // 在一个ajax响应后再执行一下取消操作，把已经完成的请求从pending中移除
    // 移除成功请求记录
    CancelRequest.removeRequestKey(response.config)
    /**
     * 下面的注释为通过response自定义code来标示请求状态，当code返回如下情况为权限有问题，登出并返回到登录页
     * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
     */
    const headers = response.headers
    if (headers['content-type'] === 'application/octet-stream') {
      return response
    }
    if (headers['content-type'] === 'application/vnd.ms-excel;charset=utf-8' || headers['content-type'] === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8') {
      return response
    }
    if (headers['content-type'] === 'application/force-download' || headers['content-type'] === 'application/force-download;charset=UTF-8') {
      return response
    }
    // if (!getRes(response)) {
    //   Message({
    //     message: '返回数据被篡改',
    //     type: 'error',
    //     duration: 5 * 1000
    //   })
    //   return false
    // }
    try {
      response.data = response.data && JSON.parse(response.data)
    } catch (err) {

    }
    const res = response.data
    if (res.code && res.code !== '200' && res.code !== '1') {
      if (tipReLogin) {
        return
      }
      if (res.code === '401') {
        // 设置登录状态为未登录
        localStorage.setItem('isLogin', 0)
        store.dispatch('FedLogOut').then(() => {
          location.reload() // 为了重新实例化vue-router对象 避免bug
        })
        return Promise.reject(res.msg || '未登录')
      } else if (res.code === '402') {
        tipReLogin = true
        MessageBox.alert(res.msg, '提示', {
          confirmButtonText: '确定',
          showClose: false,
          closeOnPressEscape: false
        }).then(() => {
          // 设置登录状态为未登录
          localStorage.setItem('isLogin', 0)
          store.dispatch('FedLogOut').then(() => {
            tipReLogin = false
            location.reload() // 为了重新实例化vue-router对象 避免bug
          })
        })
        return Promise.reject('')
      } else {
        Message({
          message: res.msg || '网络异常',
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(res.msg || '网络异常')
      }
    } else {
      return response
    }
  },
  error => {
    CancelRequest.removeRequestKey(error.config || {})
    if (axios.isCancel(error)) {
      // 为了终结promise链 就是实际请求 不会走到.catch(rej=>{});这样就不会触发错误提示之类了。
      return new Promise(() => {
      })
    } else {
      Message({
        message: error.msg || '网络异常！',
        type: 'error',
        duration: 5 * 1000
      })
      return Promise.reject(error)
    }
  })

export default service
